서브 쿼리
개요
sql문 안에 들어간 작은 sql문을 서브쿼리라고 한다.
사용 방식
- 소괄호로 감싼 후 쿼리를 작성한다.
- 단일행, 혹은 복수행 비교 연산자와 사용 가능하다.
- 단일행 비교 연산자와 사용될 때는 당연히 결과도 한 건 이하로 나와야 한다.
- 복수행이면 딱히 단수면 안 된다 이런 건 없다.
- order by를 사용할 수 없다!
- order by는 전체 sql 문에서 하나만 올 수 있기 때문이다.
- 서브 쿼리는 결과로서만 메인 쿼리에 데이터를 제공한다.
- 서브 쿼리는 메인 쿼리의 컬럼을 사용할 수 있으나 역은 성립하지 않는다.
- where절에 메인 쿼리의 컬럼을 사용하는 경우가 대표적일 것이다.
사용되는 절
서브 쿼리가 들어가는 것이 가능한 절이 몇 개 있는데, 막상 보면 엄청 당연하게 느껴진다.
- select - 스칼라 서브 쿼리라고도 부름
- from - 인라인뷰 서브 쿼리라고도 부름
- where
- having
- insert에서 values
- update에서 set
분류
사용법에 있어서 엄청 어렵거나 한 것은 없는데, 시험에 나올 수도 있을 개념들은 미리 보자.
- 동작 방식에 따른 분류
- 비연관 서브쿼리
- 서브쿼리가 메인 쿼리의 컬럼을 가지지 않는 서브쿼리
- 주로 순수하게 메인 쿼리에 값을 제공해주고 싶을 때 사용
- 연관 서브쿼리
- 서브쿼리가 메인 쿼리의 컬럼을 가지는 서브쿼리
- 메인쿼리에서 수행된 값을 서브 쿼리에서 조건 검사를 할 때 주로 사용
- 비연관 서브쿼리
- 반환 형태에 따른 분류
- 단일행
- 실행 결과가 한 건 이하인 서브쿼리
- 항상 비교연산자와 함께 사용된다.
- 집계함수나 distinct, 혹은 where에서 기본키를 조건으로 걸면 하나의 데이터가 나오게 만들 수 있다.
- 다중행
- 한 행이 결과로 나오는 서브 쿼리
- in, all, any, some 등의 다중행 비교연산자와 사용된다.
- 다중컬럼 서브쿼리
- 여러 컬럼이 나오는 서브 쿼리
- where 절에서 사용되는 서브 쿼리가 주로 이렇게 나온다.
- 단일행
SELECT A.ADSTRD_CD
, B.ADSTRD_NM
, A.STD_YM
, A.POPLTN_SE_CD
, A.AGRDE_SE_CD
, A.POPLTN_CNT
FROM TB_POPLTN A
, TB_ADSTRD B
WHERE A.STD_YM = '202010'
AND A.POPLTN_SE_CD = 'T'
AND (A.AGRDE_SE_CD, A.POPLTN_CNT) IN
(
SELECT K.AGRDE_SE_CD
, MAX(K.POPLTN_CNT) AS POPLTN_CNT
FROM TB_POPLTN K
WHERE K.STD_YM = '202010'
AND K.POPLTN_SE_CD = 'T'
GROUP BY K.AGRDE_SE_CD
)
AND A.ADSTRD_CD = B.ADSTRD_CD
ORDER BY A.AGRDE_SE_CD
;
이것이 다중 컬럼 서브 쿼리 방식이다.
두 가지 컬럼을 select하고 조건절에서도 두가지 컬럼을 비교한다.
EXISTS
SELECT A.SUBWAY_STATN_NO
, A.LN_NM
, A.STATN_NM
FROM TB_SUBWAY_STATN A
WHERE EXISTS ( SELECT 1
FROM TB_SUBWAY_STATN_TK_GFF K
WHERE K.SUBWAY_STATN_NO = A.SUBWAY_STATN_NO
AND K.STD_YM = '202010'
AND TK_GFF_CNT >= 250000
)
ORDER BY A.SUBWAY_STATN_NO
exists 문법도 존재한다.
이것은 연관 서브쿼리를 활용할 때 해당 조건에 맞는 데이터들만 뽑을 수 있도록 해준다.
여기에서 1은 단순하게 있다는 값만 뽑기 위해 세팅한 값에 불과하다.
비연관 서브쿼리에도 할 수 있기는 한데, 그건 사실 의미가 없다.
이때 주의할 게 있다.
메인쿼리와 서브 쿼리 간 실행 순서에 대한 것이다.
exists문을 보면 알겠지만 현재 서브쿼리의 조건을 검사하기 위해서는 메인 쿼리에 각 행에 대해 연산이 돼야 한다.
즉, 메인 쿼리 각 행마다 해당 서브 쿼리가 작동한다는 것이다;;
from 절에 있을 때는 한번만 실행되지만 이렇게 연관서브쿼리, select절에 들어가는 서브쿼리는 다중으로 실행되기에 성능에 영향을 미칠 수 있다.
서브 쿼리는 쿼리를 작성하는데 있어서는 순서가 딱딱 나오니까 직관적일 수 있다.
그러나 불필요한 연산을 야기하는 경우가 많기에 항상 더 최적화할 방법은 고민해봐야 한다.
다만, 인라인 뷰를 활용할 때는 불필요하게 불러오는 행을 줄여서 성능이 향사되는 경우도 존재하니 확인해보자.
결국 서브쿼리는 나온 결과 값을 어떻게 활용해먹냐 정도의 머리를 굴려야 하고, 그 이상의 어려운 내용은 사실 없다.
그래서 지금 디비 곱창난 마당에 실습 없이 넘어가려고 한다..